﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Controls;
using NUnit.Framework;
using WPFCABShell.Shell.Interface.Services.Options;
using WPFCABShell.Shell.Services.Options;
using WPFCABShell.UnitTest.Shared;
using Microsoft.Practices.CompositeUI.UIElements;
using SCSFContrib.CompositeUI.WPF.UIElements;

namespace WPFCABShell.UnitTest.Shell.Services.Options
{
	[TestFixture]
	public sealed class OptionsServiceTest : UnitTest.Shared.UnitTest
	{
		private TestableWorkItem _workItem;
		private OptionsService _optionsService;

		protected override void SetUpCore()
		{
			base.SetUpCore();
			_workItem = new TestableWorkItem();
			_optionsService = new OptionsService(_workItem);

			_workItem.OnBuiltUp(null);

			IUIElementAdapterFactoryCatalog uiElementAdapterFactoryCatalog = _workItem.Services.Get<IUIElementAdapterFactoryCatalog>();
			uiElementAdapterFactoryCatalog.RegisterFactory(new ItemsControlUIAdapterFactory());
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Register_ShouldThrowIfTargetSiteIsNull()
		{
			IOptionsPane optionsPane = Mocks.DynamicMock<IOptionsPane>();
			_optionsService.Register(null, "name", optionsPane.GetType(), null);
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Register_ShouldThrowIfNameIsNull()
		{
			IOptionsPane optionsPane = Mocks.DynamicMock<IOptionsPane>();
			_optionsService.Register("targetSiteName", null, optionsPane.GetType(), null);
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Register_ShouldThrowIfPaneTypeIsNull()
		{
			_optionsService.Register("targetSiteName", "name", null, null);
		}

		[Test]
		[ExpectedException(typeof(ArgumentException), ExpectedMessage = "Type 'WPFCABShell.UnitTest.Shell.Services.Options.OptionsServiceTest' does not implement required IOptionsPane interface.")]
		public void Register_ShouldThrowIfPaneTypeDoesNotImplementRequiredInterface()
		{
			_optionsService.Register("targetSiteName", "name", GetType(), null);
		}

		[Test]
		public void Register_ShouldRegisterOptionsInTargetSite()
		{
			string targetSiteName = "Options";
			string siteName = "NewSite";
			_workItem.UIExtensionSites.RegisterSite(targetSiteName, new ItemsControl());
			IOptionsPane optionsPane = Mocks.DynamicMock<IOptionsPane>();
			
			IOptions options = _optionsService.Register(targetSiteName, "My Options", optionsPane.GetType(), siteName);
			Assert.IsNotNull(options);
			Assert.AreEqual("My Options", options.Name);
			Assert.AreEqual(optionsPane.GetType(), options.PaneType);
			Assert.AreEqual(targetSiteName, options.TargetSiteName);
			Assert.AreEqual(siteName, options.SiteName);
			Assert.IsTrue(_workItem.UIExtensionSites[targetSiteName].Contains(options));
		}

		[Test]
		public void Register_ShouldRegisterNewSiteIfSpecified()
		{
			string targetSiteName = "Options";
			string siteName = "NewSiteName";
			_workItem.UIExtensionSites.RegisterSite(targetSiteName, new ItemsControl());
			IOptionsPane optionsPane = Mocks.DynamicMock<IOptionsPane>();

			Assert.IsFalse(_workItem.UIExtensionSites.Contains(siteName));
			IOptions options = _optionsService.Register(targetSiteName, "My Options", optionsPane.GetType(), siteName);
			Assert.IsTrue(_workItem.UIExtensionSites.Contains(siteName));
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Unregister_ShouldThrowIfOptionsIsNull()
		{
			_optionsService.Unregister(null);
		}

		[Test]
		public void Unregister_ShouldRemoveItemFromSite()
		{
			string siteName = "Options";
			_workItem.UIExtensionSites.RegisterSite(siteName, new ItemsControl());
			IOptionsPane optionsPane = Mocks.DynamicMock<IOptionsPane>();

			IOptions options = _optionsService.Register(siteName, "My Options", optionsPane.GetType(), null);
			Assert.IsTrue(_workItem.UIExtensionSites[siteName].Contains(options));

			_optionsService.Unregister(options);
			Assert.IsFalse(_workItem.UIExtensionSites[siteName].Contains(options));
		}

		[Test]
		public void Unregister_ShouldUnregisterSiteIfSpecified()
		{
			string targetSiteName = "Options";
			string siteName = "NewSiteName";
			_workItem.UIExtensionSites.RegisterSite(targetSiteName, new ItemsControl());
			IOptionsPane optionsPane = Mocks.DynamicMock<IOptionsPane>();

			IOptions options = _optionsService.Register(targetSiteName, "My Options", optionsPane.GetType(), siteName);
			Assert.IsTrue(_workItem.UIExtensionSites.Contains(siteName));

			_optionsService.Unregister(options);
			Assert.IsFalse(_workItem.UIExtensionSites.Contains(siteName));
		}
	}
}
